/**
******************************************************************************
* @file           : studio_geo_algo_c.h
* @author         : wangyingjie
* @brief          : C 语言版几何算法库，包含常用的空间计算、线段抽稀、去除离群点等几何操作算法。
*                   提供多种几何计算函数，如计算点之间的距离、方位角、点到线段的最短距离、以及线段的抽稀处理（Douglas-Peucker算法等）。
*                   适用于笛卡尔坐标系和大地坐标系（经纬度）的应用场景。
* @attention      : None
* @date           : 2025/5/11
******************************************************************************
*/

#ifndef STUDIO_GEO_ALGO_C_H
#define STUDIO_GEO_ALGO_C_H

#include "studio_geo_c.h"

/////////////////// 基础适量算法 ///////////////////

/// 计算两点之间的距离的平方 (笛卡尔坐标系)
/// @param p1
/// @param p2
/// @return
double distance_squared_c(const studio_point_c *p1, const studio_point_c *p2);

/// 计算点到线段的距离的平方 (笛卡尔坐标系)
/// \param p 点
/// \param start 线段起点
/// \param end 线段终点
/// \return 距离的平方 （单位 米）
double point_line_dist_square_c(const studio_point_c *p, const studio_point_c *start, const studio_point_c *end);

/// 计算两点之间的方位角 (笛卡尔坐标系)
/// 方位角是从点 p_from 指向点 p_to 的向量与正北方向的顺时针夹角，单位为度
/// @param p_from
/// @param p_to
/// @return
double azimuth_angle_c(const studio_point_c *p_from, const studio_point_c *p_to);

/// 计算两个经纬度之间的距离的平方 (大地坐标系)
/// @param p1
/// @param p2
/// @return 距离的平方 （单位 米）
double distance_squared_gcs_c(const studio_point_c *p1, const studio_point_c *p2);

/// 计算经纬度点到经纬度线的距离的平方 (大地坐标系)
/// \param p 点
/// \param start 线段起点
/// \param end 线段终点
/// \return 距离的平方 （单位 米）
double point_line_dist_square_gcs_c(const studio_point_c *p, const studio_point_c *start, const studio_point_c *end);

/// 计算两点之间的方位角 (大地坐标系)
/// 方位角是从点 p_from 指向点 p_to 的向量与正北方向的顺时针夹角，单位为度
/// @param p_from
/// @param p_to
/// @return
double azimuth_angle_gcs_c(const studio_point_c *p_from, const studio_point_c *p_to);

/// <summary>
/// 计算经纬度点移动一定距离后的新点
/// </summary>
/// <param name="pt"></param>
/// <param name="delta_x">X方向移动距离，单位为米</param>
/// <param name="delta_y">Y方向移动距离，单位为米</param>
/// <returns></returns>
studio_point_c lonlat_move_by(const studio_point_c *pt, double delta_x, double delta_y);

/////////////////// 矢量(线)抽稀算法 ///////////////////

/// Douglas-Peucker算法，线段压缩
/// \param points 线段
/// \param start 线段起点索引
/// \param end 线段终点索引
/// \param epsilon 抽稀容差,若某点到当前线段的最大垂直距离超过epsilon，则保留该点,单位与适量坐标系的单位一致
/// \param indices 存储简化后的点索引
/// \param index_count 存储简化后的点索引数量
void douglas_peucker_c(const studio_line_c *points, size_t start, size_t end, double epsilon, unsigned int *indices, unsigned int *index_count, unsigned int max_indices);

/// 矢量线段抽稀算法
/// \param line 原始线段
/// \param max_points 压缩后最大点
/// \param epsilon 抽稀容差,若某点到当前线段的最大垂直距离超过epsilon，则保留该点,单位与适量坐标系的单位一致
/// \param vacuate_line 抽稀后的线段
/// \return
bool line_vacuate_c(const studio_line_c *line, const int max_points, const double epsilon, studio_line_c *vacuate_line);

/// 矢量线段抽稀算法 大地坐标系(GCS), 坐标点为十进制经纬度
/// @param line 原始线段
/// @param max_points 压缩后最大点
/// @param epsilon 抽稀容差,若某点到当前线段的最大垂直距离超过epsilon，这里单位是米
/// @param vacuate_line 抽稀后的线段
/// @return
bool line_vacuate_gcs_c(const studio_line_c *line, const int max_points, const double epsilon, studio_line_c *vacuate_line);

/////////////////// 移除线段中的离群点 ///////////////////

/**
 * @brief 去除 indices 数组中的重复元素（保持顺序，原地修改）
 * @param indices 输入数组（可能包含重复）
 * @param index_count 输入数组长度（会被更新为去重后的长度）
 */
void remove_duplicates(unsigned int *indices, unsigned int *index_count);

/// 移除线段中的离群点
/// @param line 原始线段
/// @param distance 离群点距离
/// @param outliers_line 滤波后的线段
/// @return
bool remove_outliers_c(const studio_line_c *line, double distance, studio_line_c *outliers_line);

#endif  // STUDIO_GEO_ALGO_C_H
